#include "window.h"

const int PERIOD = 1000 / 60;

Window::Window(int w, int h)
{
	x = 0;
	y = 0;
	width = w;
	height = h;

	wire_frame = false;
	debug = false;

	picture = new Picture();
}

Window::~Window()
{
}

bool Window::Initialize()
{
	return picture->Initialize();
}

void Window::TakeDown()
{
	picture->TakeDown();
}

void Window::DisplayFunc()
{
	ClearWindow();

	// wire frame toggling will affect everything drawn, so it can be set here
	glPolygonMode(GL_FRONT_AND_BACK, wire_frame ? GL_LINE : GL_FILL);
	glEnable(GL_DEPTH_TEST);

	picture->Display();
}

void Window::KeyboardFunc(unsigned char c, int x, int y)
{
	switch (c) {
		case 'x':
		case 'X':

		// escape
		case 27:
			glutLeaveMainLoop();
			return;

		case 'w':
		case 'W':
			wire_frame = !wire_frame;
			break;

		case 'd':
		case 'D':
			debug = !debug;
			break;
	}
}

void Window::MouseFunc(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		// mouse coordinates are measured from the top of the screen, but GL measures
		// coordinates from the bottom of the screen. That's why the source's y coordinate
		// is height - y rather than just y.
		glm::ivec2 source = glm::ivec2(x, this->height - y);

		// after the mouse has been clicked, the picture warps from source to destination
		// every frame, always working from the "original" picture, here meaning the image
		// when the mouse was last released. When the mouse is released, the warped image
		// becomes the new original.
		picture->SetSource(source);
		picture->SetDestination(source);
	}
}

void Window::MotionFunc(int x, int y)
{
	picture->SetDestination(glm::ivec2(x, this->height - y));
}

void Window::ReshapeFunc(int w, int h)
{
	// this prevents divide-by-zero errors
	if (h == 0)
	{
		return;
	}

	width = w;
	height = h;
	aspect = GLfloat(w / h);

	glutPostRedisplay();
}

void Window::TimerFunc(int value)
{
	extern void TimerFunc(int value);

	glutTimerFunc(PERIOD, TimerFunc, value);
	glutPostRedisplay();
}

void Window::ClearWindow()
{
	glViewport(0, 0, width, height);
	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}